package cn.wolfcode.demo.completableFuture;

import java.util.concurrent.*;

public class CompletableFutureDemo {
    //todo 使用多线程开发 可能会出现还没有执行完整个main方法都被关闭了 解决可以加CountDownLatch latch = new CountDownLatch(ids.size());
    // 也可以加自定义线程池

    //获取CPU核心数为
    public static void main11(String[] args) {
        int cpuCores = Runtime.getRuntime().availableProcessors();
        System.out.println("CPU核心数为：" + cpuCores);
    }
    public static void main2(String[] args) {
        CountDownLatch latch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            CompletableFuture.runAsync(() -> {
                try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(finalI);
                latch.countDown();
            });
        }
        try {
            latch.await(3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            //log.error("优惠方案计算被中断，{}", e.getMessage());
        }
    }
    // todo
    /**
     * CompletableFuture 使用
     * CompletableFuture对Future的改进
     * 线程池 放在第二个参数 若没有指定，则使用默认的ForkJoinPoolcommonPool（）作为它的线程池执行异步代码，如果指定线程池，则使用我们自定义的或者特别指定的线程池执行异步代码
     * 方法介绍：
     * supplyAsync 有返回值   runAsync 没有返回值
     * whenComplete 返回最近的两个数据 异常和 上个返回的值
     * exceptionally 有异常执行这里
     *
     * 获取方法介绍：
     *     ■ public T get()
     *     ■ public T get(long timeout,TimeUnit unit)
     *     ■ public T join() --->和get一样的作用，只是不需要抛出异常
     *     ■ public T getNow(T valuelfAbsent) --->计算完成就返回正常值，否则返回备胎值（传入的参数），立即获取结果不阻塞
     *   ○ 主动触发计算
     *     ■ public boolean complete(T value) ---->是否打断get方法立即返回括号值
     *
     *  返回值方法介绍：
     *   ○ thenApply --->计算结果存在依赖关系，这两个线程串行化---->由于存在依赖关系（当前步错，不走下一步），当前步骤有异常的话就叫停
     *   ○ handle --->计算结果存在依赖关系，这两个线程串行化---->有异常也可以往下走一步
     *   ■ thenRun(Runnable runnable) :任务A执行完执行B，并且不需要A的结果
     *   ■ thenAccept(Consumer action): 任务A执行完执行B，B需要A的结果，但是任务B没有返回值
     *   ■ thenApply(Function fn): 任务A执行完执行B，B需要A的结果，同时任务B有返回值
     *
     *   thenCombine方法 把两个任务的结果一起交给来处理
     *  allOf方法 等所以任务执行完
     */

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " 启动");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });

        CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " 启动");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 20;
        });

        //需要返回值 的可以then
        completableFuture2.thenAccept(d->{
            System.out.println(Thread.currentThread().getName() + " d");
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        CompletableFuture.allOf(completableFuture1,completableFuture2).join();
        long endTime = System.currentTimeMillis();
        System.out.println("----costTime: " + (endTime - startTime) + " 毫秒");
    }

    public static void main5(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " 启动");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });

        CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " 启动");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 20;
        });
        CompletableFuture<Integer> finalResult = completableFuture1.thenCombine(completableFuture2, (x, y) -> {
            System.out.println("----------开始两个结果合并");
            return x + y;
        });
        System.out.println(finalResult.join());

    }


    public static void main3(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        CompletableFuture.supplyAsync(() -> {
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int i = 10 / 0;
            System.out.println("111");
            return 1;
        }, threadPool).thenApply(a-> 3)

                .whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("----计算结果： " + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        });
      /*  CompletableFuture.runAsync(() ->{
            //暂停几秒钟线程
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("111");
        },threadPool);*/

        threadPool.shutdown();
    }


    public static void main1(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        CompletableFuture.supplyAsync(() -> {
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("111");
            return 1;
        }, threadPool).handle((f, e) -> {
            int i = 10 / 0;
            System.out.println("222");
            return f + 2;
        }).handle((f, e) -> {
            System.out.println("333");
            return f + 3;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("----计算结果： " + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        });

        System.out.println(Thread.currentThread().getName() + "----主线程先去忙其它任务");

        threadPool.shutdown();
    }
}
